home *** CD-ROM | disk | FTP | other *** search
- /*
- * $RCSfile: regenLog.c,v $
- * $Revision: 1.1.1.1 $
- * $Date: 1996/05/04 21:55:49 $
- */
- /**********************************************************************
- * EXODUS Database Toolkit Software
- * Copyright (c) 1991 Computer Sciences Department, University of
- * Wisconsin -- Madison
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
- * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
- * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * The EXODUS Project Group requests users of this software to return
- * any improvements or extensions that they make to:
- *
- * EXODUS Project Group
- * c/o David J. DeWitt and Michael J. Carey
- * Computer Sciences Department
- * University of Wisconsin -- Madison
- * Madison, WI 53706
- *
- * or exodus@cs.wisc.edu
- *
- * In addition, the EXODUS Project Group requests that users grant the
- * Computer Sciences Department rights to redistribute these changes.
- **********************************************************************/
-
- #include "sysdefs.h"
- #include "ess.h"
- #include "checking.h"
- #include "trace.h"
- #include "error.h"
- #include "list.h"
- #include "pool.h"
- #include "tid.h"
- #include "io.h"
- #include "lock.h"
- #include "object.h"
- #include "msgdefs.h"
- #include "thread.h"
- #include "semaphore.h"
- #include "latch.h"
- #include "link.h"
- #include "lsn.h"
- #include "bf.h"
- #include "volume.h"
- #include "openlog.h"
- #include "trans.h"
- #include "logrecs.h"
- #include "log_intfuncs.h"
- #include "log_extfuncs.h"
- #include "bf_extfuncs.h"
- #include "util_funcs.h"
- #include "thread_globals.h"
- #include "trans_globals.h"
- #include "log_globals.h"
- #include "io_globals.h"
-
-
- int
- regenLog (
-
- register OPENLOG *openLog
- )
- {
-
- register PAGEHASH *tailBuffer;
- GROUPLINK *tailLink;
- LOGPAGEHDR *pageHeader;
- LOGPAGEHDR *endHeader;
- LOGRECORDHDR *record;
- CHECKPOINTMASTER *checkMaster;
- CHECKPOINTINFO *checkInfo;
- PID pid;
- int i;
- int initWrapCount;
- PAGEHASH *pageHashList[MAX_IO_LIST];
- int numToForce;
-
- TRACE(TR_LOG, TR_LEVEL_1);
-
- /* get the latch on the log */
- if (waitLatch( &(openLog->logLatch), EXCLUSIVE_LATCH) ) {
-
- SM_ERROR(TYPE_FATAL, Active->errno);
- }
-
- /* get the semaphore on the log */
- if (waitSemaphore( &(openLog->writeSemaphore) )) {
-
- SM_ERROR(TYPE_FATAL, Active->errno);
- }
-
- /*
- * Record the regen/recovery state of the log
- * so that other log writers will wait.
- */
- TransInfo.logState = L_RECOVER;
-
- /*
- * The initial value for the wrapCount is the wrapCount on
- * volume header +1
- */
- initWrapCount = (int) openLog->volRec->header->dismountEndOfLog.wrapCount + 1;
-
- /* zero out the control page which destroys the log */
- bzero(openLog->controlBuffer->bufFrame, MIN_PAGESIZE);
-
- /*
- * dirty the page (get the semaphore to make the debugging
- * version of DIRTY_PAGE happy
- */
- #ifdef DEBUG
- waitSemaphore(&(openLog->controlBuffer->pageHash->semaphore));
- #endif
- DIRTY_PAGE(openLog->controlBuffer->pageHash);
- #ifdef DEBUG
- signalSemaphore(&(openLog->controlBuffer->pageHash->semaphore));
- #endif
-
- /* force it to disk */
- bf_ForcePage(openLog->controlBuffer->pageHash, BF_SEM);
-
- /* contruct a pid nulling out the log */
- pid.volid = openLog->volid;
- pid.page = openLog->logFileAddr;
-
- /* make sure I/O is asynchronous */
- PREVENT_FAST_IO();
-
- /*
- * null out all pages of the log
- */
- numToForce = 0;
- for (i = 0; i < openLog->filePages; i++, pid.page += openLog->blocksPerPage) {
-
- register GROUPLINK *tempLink;
-
- if (numToForce == MAX_IO_LIST) {
- bf_ForcePageList(pageHashList, numToForce, BF_SEM);
- numToForce = 0;
- }
-
- /*
- * read the first log page into the cache
- */
- if ((tempLink = bf_ReadPage(openLog->writeGroup, &pid,
- openLog->page2size, BF_SEM | BF_NOREAD)) == NULL) {
-
- SM_ERROR(TYPE_FATAL, Active->errno);
- }
-
- /*
- * zero the page
- */
- bzero(tempLink->bufFrame, (int) openLog->pageSize);
-
- /*
- * get a pointer to the header of the page
- */
- pageHeader = (LOGPAGEHDR *) tempLink->bufFrame;
-
- /*
- * initialize the page header
- */
- pageHeader->magic = LOGPAGE_MAGIC;
- pageHeader->pageNumber = i;
- pageHeader->wrapCount = NULL_LOG_WRAP_COUNT;
- pageHeader->lastRecord = NULL_LAST_RECORD;
-
- /*
- * get a pointer to the end of the page
- * initialize the header on the page
- */
- endHeader = (LOGPAGEHDR *) (((char *) pageHeader) + openLog->lastUsableByte);
- *endHeader = *pageHeader;
-
- /*
- * dirty the page
- */
- DIRTY_PAGE(tempLink->pageHash);
-
- /*
- * mark this as a log page
- */
- PSET_PAGE_TYPE(tempLink->pageHash, PAGE_LOG);
-
- /*
- * Give the tail of the log a dummy force mark so
- * that preflushLog() will flush it
- OpenLog.tailBuffer = tempLink->pageHash;
- OpenLog.tailBuffer->forceMark = i+1;
- openLog->tailLink = tempLink;
- */
-
- /*
- * unfix the page
- */
- signalSemaphore(&(tempLink->pageHash->semaphore));
- bf_UnfixPage(tempLink, BF_DEFAULT, FALSE);
-
- pageHashList[numToForce] = tempLink->pageHash;
- numToForce++;
- }
-
- /*
- * force rest of log to disk
- */
- if (numToForce > 0) {
- bf_ForcePageList(pageHashList, numToForce, BF_SEM);
- numToForce = 0;
- }
-
- /* allow server to perform I/O itself (synchrounous) */
- ALLOW_FAST_IO();
-
- /*
- * contruct a pid for reading the page
- */
- pid.volid = openLog->volid;
- pid.page = openLog->logFileAddr;
-
- /*
- * read the first log page into the cache
- */
- if ((tailLink = bf_ReadPage(openLog->writeGroup, &pid,
- openLog->page2size, BF_SEM )) == NULL) {
-
- SM_ERROR(TYPE_FATAL, Active->errno);
- }
-
- /*
- * get a pointer to the page hash
- */
- tailBuffer = tailLink->pageHash;
-
- /*
- * mark the page as a log buffer
- */
- PSET_PAGE_TYPE(tailBuffer, PAGE_LOG);
-
- /*
- * get a pointer to the header of the page
- */
- pageHeader = (LOGPAGEHDR *) tailBuffer->bufFrame;
-
- /*
- * initialize the page header
- */
- pageHeader->magic = LOGPAGE_MAGIC;
- pageHeader->wrapCount = initWrapCount;
- pageHeader->lastRecord = NULL_LAST_RECORD;
-
- /*
- * get a pointer to the end of the page
- */
- endHeader = (LOGPAGEHDR *) (((char *) pageHeader) + openLog->lastUsableByte);
-
- /*
- * initialize the header on the page
- */
- endHeader->magic = LOGPAGE_MAGIC;
- endHeader->wrapCount = initWrapCount;
- endHeader->lastRecord = NULL_LAST_RECORD;
-
- /*
- * set the checkpoint information
- */
- openLog->checkPointPid = 0;
- openLog->checkPointLSN.offset = FIRST_LSN;
- openLog->checkPointLSN.wrapCount = 1;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("checkPointLSN:%d", openLog->checkPointLSN.offset));
-
- /*
- * get a pointer to where the checkpoint record resides
- */
- record = (LOGRECORDHDR *) (tailBuffer->bufFrame + FIRST_LSN);
-
- /*
- * record the initial checkpoint
- */
- record->magic = LOGRECORD_MAGIC;
- record->length = sizeof(LOGRECORDHDR) + sizeof(CHECKPOINTINFO);
- record->type = LOG_REC_TYPE_CHECKPOINT;
- record->recordLSN = openLog->checkPointLSN;
- record->tid = NULL_TID;
- record->previousLSN = NULL_LSN;
- record->imageCount = 1;
-
- /*
- * setup the image
- */
- record->imageOffset[0] = 0;
- record->imageSize[0] = sizeof(CHECKPOINTINFO);
-
- /*
- * get a pointer to the checkpoint info record
- */
- checkInfo = (CHECKPOINTINFO *) (((char *) record) + sizeof(LOGRECORDHDR));
-
- /*
- * fill in the body field
- */
- checkInfo->numActiveTrans = 0;
- checkInfo->numDirtyPages = 0;
- checkInfo->wrapCount = initWrapCount;
-
- /*
- * set the openlog information
- */
- openLog->tailBuffer = tailBuffer;
- openLog->tailLink = tailLink;
- openLog->wrapCount = initWrapCount;
- openLog->tailLSN = FIRST_LSN + record->length;
- openLog->tailPid = 0;
- openLog->activePid = NULLPID;
- openLog->nextValidLSN.wrapCount = initWrapCount;
- openLog->nextValidLSN.offset = openLog->tailLSN;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("tailLSN:%d", openLog->tailLSN));
-
- /*
- * fill in the lastRecord field
- */
- pageHeader->lastRecord = FIRST_LSN;
- endHeader->lastRecord = FIRST_LSN;
-
- /*
- * put non-zero first and force mark
- */
- tailBuffer->forceMark = tailBuffer->firstMark = 1;
-
- /*
- * dirty the page
- */
- DIRTY_PAGE(tailBuffer);
-
- /*
- * force it to disk
- */
- bf_ForcePage(tailBuffer, NOFLAGS);
-
- /*
- * unfix the page
- */
- signalSemaphore(&(tailLink->pageHash->semaphore));
- bf_UnfixPage(tailLink, BF_DEFAULT, FALSE);
-
- /*
- * get a pointer to the checkpoint pointer page
- */
- checkMaster = (CHECKPOINTMASTER *) openLog->controlBuffer->bufFrame;
-
- /*
- * zero out the page
- */
- bzero(openLog->controlBuffer->bufFrame, MIN_PAGESIZE);
-
- /*
- * record the location of the initial checkpoint
- */
- checkMaster->magic = CHECKPOINTMASTER_MAGIC;
- checkMaster->wrapCount = initWrapCount;
- checkMaster->oldestDirtyLSN = FIRST_LSN;
- checkMaster->checkRecordLSN.offset = FIRST_LSN;
- checkMaster->checkRecordLSN.wrapCount = initWrapCount;
-
- /*
- * dirty the page (get the semaphore to make the
- * debugging version of DIRTY_PAGE happy)
- */
- #ifdef DEBUG
- waitSemaphore(&(openLog->controlBuffer->pageHash->semaphore));
- #endif
- DIRTY_PAGE(openLog->controlBuffer->pageHash);
- #ifdef DEBUG
- signalSemaphore(&(openLog->controlBuffer->pageHash->semaphore));
- #endif
-
- /*
- * force it to disk
- */
- bf_ForcePage(openLog->controlBuffer->pageHash, BF_SEM);
-
- /* mark the volume as regenerated */
- openLog->volRec->header->dismountEndOfLog.wrapCount = 1;
- openLog->volRec->dirty = TRUE;
- DIRTY_PAGE(openLog->volRec->headerLink->pageHash);
- bf_ForcePage(openLog->volRec->headerLink->pageHash, BF_SEM);
-
- /* remember this checkpoint */
- LastFlushedCheckpoint = checkMaster->checkRecordLSN;
- OldestDirtyPageLSN = LastFlushedCheckpoint;
-
- /*
- * set up a new transaction record
- */
- TransInfo.tidSequence = 1;
-
- /*
- * give back the latch and the semaphore
- */
- signalSemaphore( &(openLog->writeSemaphore) );
- signalLatch( &(openLog->logLatch) );
-
- /*
- * return success
- */
- return(esmNOERROR);
- }
-